Imports System
Imports System.Xml
Imports System.Threading
Imports System.Runtime.InteropServices
Imports Microsoft.SqlServer.Dts.Runtime

<System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable")> _
<Guid("776C6DA1-12DB-47BC-B857-6DC583D60B86"), _
DtsTask(DisplayName:="Auditing Control (NCL)", _
        Description:="Auditing Control (NCL SQL2005)", _
        IconResource:="NCL.SSIS.ControlFlow.Audit.ico", _
        UITypeName:="NCL.SSIS.ControlFlow.AuditUISQL2005,NCL.SSIS.ControlFlow.AuditSQL2005,Version=1.0.0.0,Culture=Neutral,PublicKeyToken=4d910ec190ff35d7")> _
Public Class AuditSQL2005
    Inherits Task
    Implements IDTSComponentPersist, IDTSBreakpointSite

#Region "Variable Declares"
    Private _oAuditConfig As New AuditConfig
    Private _iAuditPackageExecutionId As Integer = -1
    Private _iParentAuditPackageExecutionId As Integer = -1
    Private _iAuditTableExecutionId As Integer = -1

    'Private initialValueInternal As Integer
    'Private loopCountValue As Integer
    'Private incrementValueInternal As Integer
    'Private postExecutionValue As Integer
    Private suspendRequiredValue As Integer
    Private debugModeValue As Integer

    Private bpm As BreakpointManager
    Private eventInfosValue As EventInfos
    Private OnBeforePackageAuditStartParent As EventInfo
    Private OnAfterPackageAuditStartParent As EventInfo
    Private OnAfterPackageAuditStartEnd As EventInfo
    Private OnBeforePackageAuditStart As EventInfo
    Private OnAfterPackageAuditStart As EventInfo
    Private OnAfterPackageAuditEnd As EventInfo
    Private OnBeforeTableAuditStart As EventInfo
    Private OnAfterTableAuditStart As EventInfo
    Private OnAfterTableAuditEnd As EventInfo
    Private suspended As ManualResetEvent
    Private canExecute As ManualResetEvent

    ' Provided when firing events.
    ' When return variable is set to false event will not be fired again.
    'Private bFireOnAfterIncrement As Boolean = True
    'Private bFireOnBeforeIncrement As Boolean = True
    'Private bFireError As Boolean = True
    'Private bFireWarning As Boolean = True
#End Region

#Region "Ctor"
    Public Sub New()
        Me.suspended = New ManualResetEvent(True)
        Me.canExecute = New ManualResetEvent(True)
    End Sub
#End Region

#Region "Task Base Class overrides"
    ''' <summary>
    ''' Called by the DTS Runtime Engine after creating the task. The EventInfos object is used 
    ''' to declare the custom OnBeforeIncrement and OnAfterIncrement events this task raises during exeuction. 
    ''' </summary>
    ''' <param name="connections">The package's Connections collection.</param>
    ''' <param name="variableDispenser">The System variables visible to the task.</param>
    ''' <param name="events">Used to raise events during execution.</param>
    ''' <param name="log">Used to write log entries.</param>
    ''' <param name="eventInfos">The EventInfos object</param>
    Public Overrides Sub InitializeTask(ByVal connections As Connections, ByVal variableDispenser As VariableDispenser, ByVal events As IDTSInfoEvents, ByVal log As IDTSLogging, ByVal eventInfos As EventInfos, ByVal logEntryInfos As LogEntryInfos, ByVal refTracker As ObjectReferenceTracker)
        If eventInfos Is Nothing Then
            Throw New ArgumentNullException("eventInfos")
        End If

        Me.eventInfosValue = eventInfos
        Dim paramNames(0) As String
        Dim paramTypes() As TypeCode = {TypeCode.Int32}
        Dim paramDescriptions(0) As String

        'paramNames(0) = "InitialValue"
        'paramDescriptions(0) = "The value before increment."

        'Me.eventInfosValue.Add("OnBeforeIncrement", "Fires before the task increments the value.", True, paramNames, paramTypes, paramDescriptions)
        'Me.onBeforeIncrement = Me.eventInfosValue("OnBeforeIncrement")

        'paramDescriptions(0) = "The value after increment."
        'Me.eventInfosValue.Add("OnAfterIncrement", "Fires after the initial value is updated.", True, paramNames, paramTypes, paramDescriptions)
        'Me.onAfterIncrement = Me.eventInfosValue("OnAfterIncrement")

        'Parent Package
        paramNames(0) = "ParentAuditPackageExecutionId"

        paramDescriptions(0) = "The value of the Parent Audit Package Execution Id."
        Me.eventInfosValue.Add("OnBeforePackageAuditStartParent", "Fires before the parent package audit is started (Parent).", True, paramNames, paramTypes, paramDescriptions)
        Me.OnBeforePackageAuditStartParent = Me.eventInfosValue("OnBeforePackageAuditStartParent")

        paramDescriptions(0) = "The value of the Parent Audit Package Execution Id."
        Me.eventInfosValue.Add("OnAfterPackageAuditStartParent", "Fires after the parent package audit is started (Parent).", True, paramNames, paramTypes, paramDescriptions)
        Me.OnAfterPackageAuditStartParent = Me.eventInfosValue("OnAfterPackageAuditStartParent")

        paramDescriptions(0) = "The value of the Parent Audit Package Execution Id."
        Me.eventInfosValue.Add("OnAfterPackageAuditStartEnd", "Fires after the parent package audit is stopped (Parent).", True, paramNames, paramTypes, paramDescriptions)
        Me.OnAfterPackageAuditStartEnd = Me.eventInfosValue("OnAfterPackageAuditStartEnd")

        'This Package
        paramNames(0) = "AuditPackageExecutionId"

        paramDescriptions(0) = "The value of the Audit Package Execution Id before package audit started."
        Me.eventInfosValue.Add("OnBeforePackageAuditStart", "Fires before the package audit is started.", True, paramNames, paramTypes, paramDescriptions)
        Me.OnBeforePackageAuditStart = Me.eventInfosValue("OnBeforePackageAuditStart")

        paramDescriptions(0) = "The value of the Audit Package Execution Id after package audit started."
        Me.eventInfosValue.Add("OnAfterPackageAuditStart", "Fires after the package audit is started.", True, paramNames, paramTypes, paramDescriptions)
        Me.OnAfterPackageAuditStart = Me.eventInfosValue("OnAfterPackageAuditStart")

        paramDescriptions(0) = "The value of the Audit Package Execution Id after package audit stopped."
        Me.eventInfosValue.Add("OnAfterPackageAuditEnd", "Fires after the package audit is stopped.", True, paramNames, paramTypes, paramDescriptions)
        Me.OnAfterPackageAuditEnd = Me.eventInfosValue("OnAfterPackageAuditEnd")

        'Table
        paramNames(0) = "AuditTableExecutionId"

        paramDescriptions(0) = "The value of the Audit Table Execution Id before table audit started."
        Me.eventInfosValue.Add("OnBeforeTableAuditStart", "Fires Before the table audit is started.", True, paramNames, paramTypes, paramDescriptions)
        Me.OnBeforeTableAuditStart = Me.eventInfosValue("OnBeforeTableAuditStart")

        paramDescriptions(0) = "The value of the Audit Table Execution Id after table audit started."
        Me.eventInfosValue.Add("OnAfterTableAuditStart", "Fires after the table audit is started.", True, paramNames, paramTypes, paramDescriptions)
        Me.OnAfterTableAuditStart = Me.eventInfosValue("OnAfterTableAuditStart")

        paramDescriptions(0) = "The value of the Audit Table Execution Id after table audit stopped."
        Me.eventInfosValue.Add("OnAfterTableAuditEnd", "Fires after the table audit is stopped.", True, paramNames, paramTypes, paramDescriptions)
        Me.OnAfterTableAuditEnd = Me.eventInfosValue("OnAfterTableAuditEnd")
    End Sub

    ''' <summary>
    ''' Called by the TaskHost.
    ''' </summary>
    ''' <param name="connections">The package's Connections collection.</param>
    ''' <param name="variableDispenser">The System variables visible to the task.</param>
    ''' <param name="componentEvents">Used to raise events during execution.</param>
    ''' <param name="log">Used to write log entries.</param>
    ''' <param name="transaction">Used to enlist in transactions.</param>
    ''' <returns>Returns a value from the DTSExecResult enumeration indicating execution success or failure.</returns>
    <System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")> _
    <System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters", MessageId:="System.Exception.#ctor(System.String)")> _
    Public Overrides Function Execute(ByVal connections As Connections, ByVal variableDispenser As VariableDispenser, ByVal componentEvents As IDTSComponentEvents, ByVal log As IDTSLogging, ByVal transaction As Object) As DTSExecResult
        If componentEvents Is Nothing Then
            Throw New ArgumentNullException("componentEvents")
        End If

        Dim _bExecPkgStart, _bExecPkgEnd, _bExecTblStart, _bExecTblEnd As Boolean
        Dim _oAuditConnection As AuditConnection

        ' While a task is not executing it is suspended.  Now that we are executing,
        ' change to not suspended.
        ChangeEvent(suspended, False)

        ' Check for a suspend before doing any work in case the suspend and execute calls
        ' were initiated at virtually the same time.
        CheckAndSuspend()

        If componentEvents.FireQueryCancel() = True Then
            Return DTSExecResult.Canceled
        End If

        'Check to see if we are going to do anything, if so then look at the values seperately
        If _oAuditConfig.AuditPackageExecutionMode = AuditExecutionMode.ExecStart _
             Or _oAuditConfig.AuditPackageExecutionMode = AuditExecutionMode.ExecEnd _
             Or _oAuditConfig.AuditTableExecutionMode = AuditExecutionMode.ExecStart _
             Or _oAuditConfig.AuditTableExecutionMode = AuditExecutionMode.ExecEnd Then
            'Do Setup

            'Get Audit Database Conection and type
            _oAuditConnection = GetConnectionForConnectionName(connections, _oAuditConfig.AuditDatabaseConnectionName)

            'Check to see if we got anything.
            If _oAuditConnection Is Nothing Then
                Throw New ApplicationException("The selected connection cannot be found, please adjust the task properties.")
            End If

            'Start Checking Individually
            If _oAuditConfig.AuditPackageExecutionMode = AuditExecutionMode.ExecStart Then
                _bExecPkgStart = ExecPackageAuditStart(_oAuditConnection, variableDispenser, componentEvents)
            Else
                _bExecPkgStart = True
            End If

            If _oAuditConfig.AuditPackageExecutionMode = AuditExecutionMode.ExecEnd Then
                _bExecPkgEnd = ExecPackageAuditEnd(_oAuditConnection, variableDispenser, componentEvents)
            Else
                _bExecPkgEnd = True
            End If

            If _oAuditConfig.AuditTableExecutionMode = AuditExecutionMode.ExecStart Then
                _bExecTblStart = ExecTableAuditStart(_oAuditConnection, variableDispenser, componentEvents)
            Else
                _bExecTblStart = True
            End If

            If _oAuditConfig.AuditTableExecutionMode = AuditExecutionMode.ExecEnd Then
                _bExecTblEnd = ExecTableAuditEnd(_oAuditConnection, variableDispenser, componentEvents)
            Else
                _bExecTblEnd = True
            End If
        End If

        ChangeEvent(suspended, True)

        If _bExecPkgStart = True And _bExecPkgEnd = True And _bExecTblStart = True And _bExecTblEnd = True Then
            Return DTSExecResult.Success
        Else
            Return DTSExecResult.Failure
        End If

        '-----------------------------
        'Old Sample code to be removed
        '-----------------------------

        'Me.postExecutionValue = Me.initialValueInternal

        'If Me.loopCountValue = 0 Then
        '     Throw New Exception("LoopCount is zero.")
        'End If

        'Dim arguments(0) As Object

        'For x As Integer = 0 To (Me.loopCountValue)
        '     Me.CheckAndFireBreakpoint(componentEvents, 1)
        '     '	Fire the OnBeforeIncrement event
        '     arguments(0) = Me.postExecutionValue
        '     If bFireOnBeforeIncrement Then
        '          componentEvents.FireCustomEvent(Me.onBeforeIncrement.Name, Me.onBeforeIncrement.Description, arguments, Nothing, bFireOnBeforeIncrement)
        '     End If

        '     Me.CheckAndFireBreakpoint(componentEvents, 2)
        '     ' increment/decrement the initial value
        '     Me.postExecutionValue += Me.incrementValueInternal

        '     '	Fire the onAfter increment event
        '     arguments(0) = Me.postExecutionValue
        '     If bFireOnAfterIncrement Then
        '          componentEvents.FireCustomEvent(Me.onAfterIncrement.Name, Me.onAfterIncrement.Description, arguments, Nothing, bFireOnAfterIncrement)
        '     End If
        'Next

        'ChangeEvent(suspended, True)
        'Return DTSExecResult.Success
    End Function

    ''' <summary>
    ''' Called by the TaskHost object. Verifies that the LoopCount, InitialValue, and IncrementValues are set correctly.
    ''' </summary>
    ''' <param name="connections">The package's Connections collection.</param>
    ''' <param name="variableDispenser">The System variables visible to the task.</param>
    ''' <param name="componentEvents">Used to raise events during execution.</param>
    ''' <param name="log">Used to write log entries.</param>
    ''' <returns>Returns a value from the DTSExecResult enumeration indicating validation success or failure.</returns>
    Public Overrides Function Validate(ByVal connections As Connections, ByVal variableDispenser As VariableDispenser, ByVal componentEvents As IDTSComponentEvents, ByVal log As IDTSLogging) As DTSExecResult
        If componentEvents Is Nothing Then
            Throw New ArgumentNullException("componentEvents")
        End If

        Dim _bValidationSuccess As Boolean

        _bValidationSuccess = _oAuditConfig.ValidateConfig(componentEvents)

        If _bValidationSuccess = True Then
            Return DTSExecResult.Success
        Else
            Return DTSExecResult.Failure
        End If

        'If Me.loopCountValue = 0 Then
        '     If bFireError Then
        '          componentEvents.FireError(0, "IncrementTask", "LoopCount cannot be zero.", "", 0)
        '     End If

        '     Return DTSExecResult.Failure
        'ElseIf Me.incrementValueInternal = 0 Then
        '     If bFireWarning Then
        '          componentEvents.FireWarning(0, "IncrementTask", "The IncrementValue property is zero.", "", 0)
        '     End If
        'End If

        'Return DTSExecResult.Success
    End Function

    '''' <summary>
    '''' Returns the result of the Execution of the task
    '''' property.
    '''' </summary>
    'Public Overrides ReadOnly Property ExecutionValue() As Object
    '     Get
    '          Return Me.postExecutionValue
    '     End Get
    'End Property
#End Region

#Region "Config Properties"
    Public Property AuditDatabaseConnectionName() As String
        Get
            Return _oAuditConfig.AuditDatabaseConnectionName
        End Get
        Set(ByVal value As String)
            _oAuditConfig.AuditDatabaseConnectionName = value.Trim
        End Set
    End Property

    Public Property AuditDatabaseConnectionGUID() As String
        Get
            Return _oAuditConfig.AuditDatabaseConnectionGUID
        End Get
        Set(ByVal value As String)
            _oAuditConfig.AuditDatabaseConnectionGUID = value.Trim
        End Set
    End Property

    Public Property AuditPackageExecutionMode() As Integer
        Get
            Return _oAuditConfig.AuditPackageExecutionMode
        End Get
        Set(ByVal value As Integer)
            _oAuditConfig.AuditPackageExecutionMode = CType(value, AuditExecutionMode)
        End Set
    End Property

    Public Property AuditPackageRunAsMaster() As Integer
        Get
            Return _oAuditConfig.AuditPackageRunAsMaster
        End Get
        Set(ByVal value As Integer)
            _oAuditConfig.AuditPackageRunAsMaster = CType(value, AuditRunAsMaster)
        End Set
    End Property

    Public Property AuditParentPackageExecutionIdVariableName() As String
        Get
            Return _oAuditConfig.AuditParentPackageExecutionIdVariableName
        End Get
        Set(ByVal value As String)
            _oAuditConfig.AuditParentPackageExecutionIdVariableName = value.Trim
        End Set
    End Property

    Public Property AuditThisPackageExecutionIdVariableName() As String
        Get
            Return _oAuditConfig.AuditThisPackageExecutionIdVariableName
        End Get
        Set(ByVal value As String)
            _oAuditConfig.AuditThisPackageExecutionIdVariableName = value.Trim
        End Set
    End Property

    Public Property AuditPackageExecutionStatus() As Integer
        Get
            Return _oAuditConfig.AuditPackageExecutionStatus
        End Get
        Set(ByVal value As Integer)
            _oAuditConfig.AuditPackageExecutionStatus = CType(value, AuditExecutionStatus)
        End Set
    End Property

    Public Property AuditPackageExecutionVariableName() As String
        Get
            Return _oAuditConfig.AuditPackageExecutionVariableName
        End Get
        Set(ByVal value As String)
            _oAuditConfig.AuditPackageExecutionVariableName = value.Trim
        End Set
    End Property

    Public Property AuditTableExecutionMode() As Integer
        Get
            Return _oAuditConfig.AuditTableExecutionMode
        End Get
        Set(ByVal value As Integer)
            _oAuditConfig.AuditTableExecutionMode = CType(value, AuditExecutionMode)
        End Set
    End Property

    Public Property AuditedDatabaseConnectionName() As String
        Get
            Return _oAuditConfig.AuditedDatabaseConnectionName
        End Get
        Set(ByVal value As String)
            _oAuditConfig.AuditedDatabaseConnectionName = value.Trim
        End Set
    End Property

    Public Property AuditedDatabaseConnectionGUID() As String
        Get
            Return _oAuditConfig.AuditedDatabaseConnectionGUID
        End Get
        Set(ByVal value As String)
            _oAuditConfig.AuditedDatabaseConnectionGUID = value.Trim
        End Set
    End Property

    Public Property AuditTableExecutionIdVariableName() As String
        Get
            Return _oAuditConfig.AuditTableExecutionIdVariableName
        End Get
        Set(ByVal value As String)
            _oAuditConfig.AuditTableExecutionIdVariableName = value.Trim
        End Set
    End Property

    Public Property AuditTableSchemaName() As String
        Get
            Return _oAuditConfig.AuditTableSchemaName
        End Get
        Set(ByVal value As String)
            _oAuditConfig.AuditTableSchemaName = value.Trim
        End Set
    End Property

    Public Property AuditTableName() As String
        Get
            Return _oAuditConfig.AuditTableName
        End Get
        Set(ByVal value As String)
            _oAuditConfig.AuditTableName = value.Trim
        End Set
    End Property

    Public Property AuditTableStartRowCountAction() As Integer
        Get
            Return _oAuditConfig.AuditTableStartRowCountAction
        End Get
        Set(ByVal value As Integer)
            _oAuditConfig.AuditTableStartRowCountAction = CType(value, AuditTableAction)
        End Set
    End Property

    Public Property AuditTableStartRowCountVariableName() As String
        Get
            Return _oAuditConfig.AuditTableStartRowCountVariableName
        End Get
        Set(ByVal value As String)
            _oAuditConfig.AuditTableStartRowCountVariableName = value.Trim
        End Set
    End Property

    Public Property AuditTableStartRowCountQuery() As String
        Get
            Return _oAuditConfig.AuditTableStartRowCountQuery
        End Get
        Set(ByVal value As String)
            _oAuditConfig.AuditTableStartRowCountQuery = value.Trim
        End Set
    End Property

    Public Property AuditTableUpdateRowCountVariableName() As String
        Get
            Return _oAuditConfig.AuditTableUpdateRowCountVariableName
        End Get
        Set(ByVal value As String)
            _oAuditConfig.AuditTableUpdateRowCountVariableName = value.Trim
        End Set
    End Property

    Public Property AuditTableInsertRowCountAction() As Integer
        Get
            Return _oAuditConfig.AuditTableInsertRowCountAction
        End Get
        Set(ByVal value As Integer)
            _oAuditConfig.AuditTableInsertRowCountAction = CType(value, AuditTableAction)
        End Set
    End Property

    Public Property AuditTableInsertRowCountVariableName() As String
        Get
            Return _oAuditConfig.AuditTableInsertRowCountVariableName
        End Get
        Set(ByVal value As String)
            _oAuditConfig.AuditTableInsertRowCountVariableName = value.Trim
        End Set
    End Property

    Public Property AuditTableInsertRowCountQuery() As String
        Get
            Return _oAuditConfig.AuditTableInsertRowCountQuery
        End Get
        Set(ByVal value As String)
            _oAuditConfig.AuditTableInsertRowCountQuery = value.Trim
        End Set
    End Property

    Public Property AuditTableDeleteRowCountVariableName() As String
        Get
            Return _oAuditConfig.AuditTableDeleteRowCountVariableName
        End Get
        Set(ByVal value As String)
            _oAuditConfig.AuditTableDeleteRowCountVariableName = value.Trim
        End Set
    End Property

    Public Property AuditTableErrorRowCountVariableName() As String
        Get
            Return _oAuditConfig.AuditTableErrorRowCountVariableName
        End Get
        Set(ByVal value As String)
            _oAuditConfig.AuditTableErrorRowCountVariableName = value.Trim
        End Set
    End Property

    Public Property AuditTableEndingRowCountAction() As Integer
        Get
            Return _oAuditConfig.AuditTableEndingRowCountAction
        End Get
        Set(ByVal value As Integer)
            _oAuditConfig.AuditTableEndingRowCountAction = CType(value, AuditTableAction)
        End Set
    End Property

    Public Property AuditTableEndingRowCountVariableName() As String
        Get
            Return _oAuditConfig.AuditTableEndingRowCountVariableName
        End Get
        Set(ByVal value As String)
            _oAuditConfig.AuditTableEndingRowCountVariableName = value.Trim
        End Set
    End Property

    Public Property AuditTableEndingRowCountQuery() As String
        Get
            Return _oAuditConfig.AuditTableEndingRowCountQuery
        End Get
        Set(ByVal value As String)
            _oAuditConfig.AuditTableEndingRowCountQuery = value.Trim
        End Set
    End Property

    Public Property AuditTableExecutionStatus() As Integer
        Get
            Return _oAuditConfig.AuditTableExecutionStatus
        End Get
        Set(ByVal value As Integer)
            _oAuditConfig.AuditTableExecutionStatus = CType(value, AuditExecutionStatus)
        End Set
    End Property

    Public Property AuditTableExecutionVariableName() As String
        Get
            Return _oAuditConfig.AuditTableExecutionVariableName
        End Get
        Set(ByVal value As String)
            _oAuditConfig.AuditTableExecutionVariableName = value.Trim
        End Set
    End Property

    Public Property UserSelectedTaskName() As String
        Get
            Return _oAuditConfig.UserSelectedTaskName
        End Get
        Set(ByVal value As String)
            _oAuditConfig.UserSelectedTaskName = value.Trim
        End Set
    End Property
#End Region

#Region "Run-Time Values"
    Public ReadOnly Property AuditPackageExecutionId() As Integer
        Get
            Return _iAuditPackageExecutionId
        End Get
    End Property

    Public ReadOnly Property ParentAuditPackageExecutionId() As Integer
        Get
            Return _iParentAuditPackageExecutionId
        End Get
    End Property

    Public ReadOnly Property AuditTableExecutionId() As Integer
        Get
            Return _iAuditTableExecutionId
        End Get
    End Property
#End Region

#Region "Run-Time Exec"
#Region "Package Executables"
    Private Function ExecPackageAuditStart(ByVal AuditConnection As AuditConnection, ByRef variableDispenser As VariableDispenser, ByRef componentEvents As IDTSComponentEvents) As Boolean
        Dim _oArguments(0) As Object
        Dim _vVariables As Variables
        Dim _iParentExecId As Integer
        Dim _iThisPkgExecId As Integer

        variableDispenser.LockForRead(_oAuditConfig.AuditParentPackageExecutionIdVariableName)
        variableDispenser.GetVariables(_vVariables)
        _iParentExecId = CType(_vVariables("User::" & _oAuditConfig.AuditParentPackageExecutionIdVariableName).Value, Integer)
        _vVariables.Unlock()

        'Check for Whether we have a parent
        If _iParentExecId = -1 Then
            'Are we allowed to generate our our parent id
            If _oAuditConfig.AuditPackageRunAsMaster = AuditRunAsMaster.Yes _
                 Or _oAuditConfig.AuditPackageRunAsMaster = AuditRunAsMaster.Always Then

            Else 'No we are not...  That is an error

            End If
        End If




        'Dts.VariableDispenser.LockForRead("InitialRowCount")
        'Dts.VariableDispenser.GetVariables(vars)
        'y = CType(vars("User::InitialRowCount").Value, Integer)
        'vars.Unlock()

        'Dts.VariableDispenser.LockForRead("ErrorRowCount")
        'Dts.VariableDispenser.GetVariables(vars)
        'z = CType(vars("User::ErrorRowCount").Value, Integer)
        'vars.Unlock()

        ''Dts.VariableDispenser.LockForWrite("InsertRowCount")
        ''Dts.VariableDispenser.GetVariables(vars)
        'Dts.Variables("InsertRowCount").Value = x - y
        ''vars.Unlock()

        'If (z = 0) Then
        '     'Dts.VariableDispenser.LockForWrite("ProcessSuccessful")
        '     'Dts.VariableDispenser.GetVariables(vars)
        '     Dts.Variables("ProcessSuccessful").Value = "Y"
        '     'vars.Unlock()
        'Else

        'For x As Integer = 0 To (Me.loopCountValue)
        '     Me.CheckAndFireBreakpoint(componentEvents, 1)
        '     '	Fire the OnBeforeIncrement event
        '     arguments(0) = Me.postExecutionValue
        '     If bFireOnBeforeIncrement Then
        '          componentEvents.FireCustomEvent(Me.onBeforeIncrement.Name, Me.onBeforeIncrement.Description, arguments, Nothing, bFireOnBeforeIncrement)
        '     End If

        '     Me.CheckAndFireBreakpoint(componentEvents, 2)
        '     ' increment/decrement the initial value
        '     Me.postExecutionValue += Me.incrementValueInternal

        '     '	Fire the onAfter increment event
        '     arguments(0) = Me.postExecutionValue
        '     If bFireOnAfterIncrement Then
        '          componentEvents.FireCustomEvent(Me.onAfterIncrement.Name, Me.onAfterIncrement.Description, arguments, Nothing, bFireOnAfterIncrement)
        '     End If
        'Next

    End Function

    Private Function ExecPackageAuditEnd(ByVal AuditConnection As AuditConnection, ByRef variableDispenser As VariableDispenser, ByRef componentEvents As IDTSComponentEvents) As Boolean
        Dim _oArguments(0) As Object

    End Function
#End Region

#Region "Table Executables"
    Private Function ExecTableAuditStart(ByVal AuditConnection As AuditConnection, ByRef variableDispenser As VariableDispenser, ByRef componentEvents As IDTSComponentEvents) As Boolean
        Dim _oArguments(0) As Object

    End Function

    Private Function ExecTableAuditEnd(ByVal AuditConnection As AuditConnection, ByRef variableDispenser As VariableDispenser, ByRef componentEvents As IDTSComponentEvents) As Boolean
        Dim _oArguments(0) As Object

    End Function
#End Region

#Region "Run-Time Execution Helper Functions"
    Private Function GetConnectionForConnectionName(ByRef connections As Connections, ByVal ConnectionName As String) As AuditConnection
        Dim _oConnection As ConnectionManager

        ConnectionName = ConnectionName.Trim

        For Each _oConnection In connections
            If _oConnection.Name.Trim = ConnectionName Then
                If _oConnection.CreationName = "OLEDB" Then
                    Return New AuditConnection(_oConnection.Name, _oConnection.ID, _oConnection.ConnectionString, "OLEDB")
                ElseIf _oConnection.CreationName.IndexOf("ADO.NET") = 0 Then
                    Return New AuditConnection(_oConnection.Name, _oConnection.ID, _oConnection.ConnectionString, "ADO.NET")
                End If
            End If
        Next

        Return Nothing
    End Function

#End Region
#End Region

#Region "IDTSComponentPersist Members"
    ''' <summary>
    ''' Store the custom properties in the package xml.
    ''' </summary>
    ''' <param name="doc">XmlDocument provided by the DTS Runtime Engine</param>
    ''' <param name="infoEvents">IDTSInfoEvents interface</param>
    Sub SaveToXML(ByVal doc As System.Xml.XmlDocument, ByVal infoEvents As IDTSInfoEvents) Implements IDTSComponentPersist.SaveToXML
        If doc Is Nothing Then
            Throw New ArgumentNullException("doc")
        End If

        Dim taskElement As XmlElement = doc.CreateElement(String.Empty, "NCL.SSIS.ControlFlow.Audit", String.Empty)

        'AuditDatabaseConnectionName Property
        Dim _xAuditDatabaseConnectionNameAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditDatabaseConnectionName", String.Empty)
        _xAuditDatabaseConnectionNameAttribute.Value = _oAuditConfig.AuditDatabaseConnectionName.ToString(System.Globalization.CultureInfo.InvariantCulture)

        'AuditDatabaseConnectionGUID Property
        Dim _xAuditDatabaseConnectionGUIDAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditDatabaseConnectionGUID", String.Empty)
        _xAuditDatabaseConnectionGUIDAttribute.Value = _oAuditConfig.AuditDatabaseConnectionGUID.ToString(System.Globalization.CultureInfo.InvariantCulture)

        'AuditPackageExecutionMode Property
        Dim _xAuditPackageExecutionModeAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditPackageExecutionMode", String.Empty)
        _xAuditPackageExecutionModeAttribute.Value = CType(CType(_oAuditConfig.AuditPackageExecutionMode, Integer), String) '_oAuditConfig.AuditPackageExecutionMode.ToString

        'AuditPackageRunAsMaster Property
        Dim _xAuditPackageRunAsMasterAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditPackageRunAsMaster", String.Empty)
        _xAuditPackageRunAsMasterAttribute.Value = CType(CType(_oAuditConfig.AuditPackageRunAsMaster, Integer), String) '_oAuditConfig.AuditPackageRunAsMaster.ToString

        'AuditParentPackageExecutionIdVariableName Property
        Dim _xAuditParentPackageExecutionIdVariableNameAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditParentPackageExecutionIdVariableName", String.Empty)
        _xAuditParentPackageExecutionIdVariableNameAttribute.Value = _oAuditConfig.AuditParentPackageExecutionIdVariableName.ToString(System.Globalization.CultureInfo.InvariantCulture)

        'AuditThisPackageExecutionIdVariableName Property
        Dim _xAuditThisPackageExecutionIdVariableNameAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditThisPackageExecutionIdVariableName", String.Empty)
        _xAuditThisPackageExecutionIdVariableNameAttribute.Value = _oAuditConfig.AuditThisPackageExecutionIdVariableName.ToString(System.Globalization.CultureInfo.InvariantCulture)

        'AuditPackageExecutionStatus Property
        Dim _xAuditPackageExecutionStatusAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditPackageExecutionStatus", String.Empty)
        _xAuditPackageExecutionStatusAttribute.Value = CType(CType(_oAuditConfig.AuditPackageExecutionStatus, Integer), String) '_oAuditConfig.AuditPackageExecutionStatus.ToString

        'AuditPackageExecutionVariableName Property
        Dim _xAuditPackageExecutionVariableNameAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditPackageExecutionVariableName", String.Empty)
        _xAuditPackageExecutionVariableNameAttribute.Value = _oAuditConfig.AuditPackageExecutionVariableName.ToString(System.Globalization.CultureInfo.InvariantCulture)

        'AuditTableExecutionMode Property
        Dim _xAuditTableExecutionModeAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditTableExecutionMode", String.Empty)
        _xAuditTableExecutionModeAttribute.Value = CType(CType(_oAuditConfig.AuditTableExecutionMode, Integer), String) '_oAuditConfig.AuditTableExecutionMode.ToString

        'AuditedDatabaseConnectionName Property
        Dim _xAuditedDatabaseConnectionNameAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditedDatabaseConnectionName", String.Empty)
        _xAuditedDatabaseConnectionNameAttribute.Value = _oAuditConfig.AuditedDatabaseConnectionName.ToString(System.Globalization.CultureInfo.InvariantCulture)

        'AuditedDatabaseConnectionGUID Property
        Dim _xAuditedDatabaseConnectionGUIDAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditedDatabaseConnectionGUID", String.Empty)
        _xAuditedDatabaseConnectionGUIDAttribute.Value = _oAuditConfig.AuditedDatabaseConnectionGUID.ToString(System.Globalization.CultureInfo.InvariantCulture)

        'AuditTableExecutionIdVariableName Property
        Dim _xAuditTableExecutionIdVariableNameAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditTableExecutionIdVariableName", String.Empty)
        _xAuditTableExecutionIdVariableNameAttribute.Value = _oAuditConfig.AuditTableExecutionIdVariableName.ToString(System.Globalization.CultureInfo.InvariantCulture)

        'AuditTableSchemaName Property
        Dim _xAuditTableSchemaNameAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditTableSchemaName", String.Empty)
        _xAuditTableSchemaNameAttribute.Value = _oAuditConfig.AuditTableSchemaName.ToString(System.Globalization.CultureInfo.InvariantCulture)

        'AuditTableName Property
        Dim _xAuditTableNameAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditTableName", String.Empty)
        _xAuditTableNameAttribute.Value = _oAuditConfig.AuditTableName.ToString(System.Globalization.CultureInfo.InvariantCulture)

        'AuditTableStartRowCountAction Property
        Dim _xAuditTableStartRowCountActionAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditTableStartRowCountAction", String.Empty)
        _xAuditTableStartRowCountActionAttribute.Value = CType(CType(_oAuditConfig.AuditTableStartRowCountAction, Integer), String) '_oAuditConfig.AuditTableStartRowCountAction.ToString

        'AuditTableStartRowCountVariableName Property
        Dim _xAuditTableStartRowCountVariableNameAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditTableStartRowCountVariableName", String.Empty)
        _xAuditTableStartRowCountVariableNameAttribute.Value = _oAuditConfig.AuditTableStartRowCountVariableName.ToString(System.Globalization.CultureInfo.InvariantCulture)

        'AuditTableStartRowCountQuery Property
        Dim _xAuditTableStartRowCountQueryAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditTableStartRowCountQuery", String.Empty)
        _xAuditTableStartRowCountQueryAttribute.Value = _oAuditConfig.AuditTableStartRowCountQuery.ToString(System.Globalization.CultureInfo.InvariantCulture)

        'AuditTableUpdateRowCountVariableName Property
        Dim _xAuditTableUpdateRowCountVariableNameAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditTableUpdateRowCountVariableName", String.Empty)
        _xAuditTableUpdateRowCountVariableNameAttribute.Value = _oAuditConfig.AuditTableUpdateRowCountVariableName.ToString(System.Globalization.CultureInfo.InvariantCulture)

        'AuditTableInsertRowCountAction Property
        Dim _xAuditTableInsertRowCountActionAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditTableInsertRowCountAction", String.Empty)
        _xAuditTableInsertRowCountActionAttribute.Value = CType(CType(_oAuditConfig.AuditTableInsertRowCountAction, Integer), String) '_oAuditConfig.AuditTableInsertRowCountAction.ToString

        'AuditTableInsertRowCountVariableName Property
        Dim _xAuditTableInsertRowCountVariableNameAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditTableInsertRowCountVariableName", String.Empty)
        _xAuditTableInsertRowCountVariableNameAttribute.Value = _oAuditConfig.AuditTableInsertRowCountVariableName.ToString(System.Globalization.CultureInfo.InvariantCulture)

        'AuditTableInsertRowCountQuery Property
        Dim _xAuditTableInsertRowCountQueryAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditTableInsertRowCountQuery", String.Empty)
        _xAuditTableInsertRowCountQueryAttribute.Value = _oAuditConfig.AuditTableInsertRowCountQuery.ToString(System.Globalization.CultureInfo.InvariantCulture)

        'AuditTableDeleteRowCountVariableName Property
        Dim _xAuditTableDeleteRowCountVariableNameAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditTableDeleteRowCountVariableName", String.Empty)
        _xAuditTableDeleteRowCountVariableNameAttribute.Value = _oAuditConfig.AuditTableDeleteRowCountVariableName.ToString(System.Globalization.CultureInfo.InvariantCulture)

        'AuditTableErrorRowCountVariableName Property
        Dim _xAuditTableErrorRowCountVariableNameAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditTableErrorRowCountVariableName", String.Empty)
        _xAuditTableErrorRowCountVariableNameAttribute.Value = _oAuditConfig.AuditTableErrorRowCountVariableName.ToString(System.Globalization.CultureInfo.InvariantCulture)

        'AuditTableEndingRowCountAction Property
        Dim _xAuditTableEndingRowCountActionAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditTableEndingRowCountAction", String.Empty)
        _xAuditTableEndingRowCountActionAttribute.Value = CType(CType(_oAuditConfig.AuditTableEndingRowCountAction, Integer), String) '_oAuditConfig.AuditTableEndingRowCountAction.ToString

        'AuditTableEndingRowCountVariableName Property
        Dim _xAuditTableEndingRowCountVariableNameAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditTableEndingRowCountVariableName", String.Empty)
        _xAuditTableEndingRowCountVariableNameAttribute.Value = _oAuditConfig.AuditTableEndingRowCountVariableName.ToString(System.Globalization.CultureInfo.InvariantCulture)

        'AuditTableEndingRowCountQuery Property
        Dim _xAuditTableEndingRowCountQueryAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditTableEndingRowCountQuery", String.Empty)
        _xAuditTableEndingRowCountQueryAttribute.Value = _oAuditConfig.AuditTableEndingRowCountQuery.ToString(System.Globalization.CultureInfo.InvariantCulture)

        'AuditTableExecutionStatus Property
        Dim _xAuditTableExecutionStatusAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditTableExecutionStatus", String.Empty)
        _xAuditTableExecutionStatusAttribute.Value = CType(CType(_oAuditConfig.AuditTableExecutionStatus, Integer), String) '_oAuditConfig.AuditTableExecutionStatus.ToString

        'AuditTableExecutionVariableName Property
        Dim _xAuditTableExecutionVariableNameAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "AuditTableExecutionVariableName", String.Empty)
        _xAuditTableExecutionVariableNameAttribute.Value = _oAuditConfig.AuditTableExecutionVariableName.ToString(System.Globalization.CultureInfo.InvariantCulture)

        'UserSelectedTaskName Property
        Dim _xUserSelectedTaskNameAttribute As XmlAttribute = doc.CreateAttribute(String.Empty, "UserSelectedTaskName", String.Empty)
        _xUserSelectedTaskNameAttribute.Value = _oAuditConfig.UserSelectedTaskName.ToString(System.Globalization.CultureInfo.InvariantCulture)

        taskElement.Attributes.Append(_xAuditDatabaseConnectionNameAttribute)
        taskElement.Attributes.Append(_xAuditDatabaseConnectionGUIDAttribute)
        taskElement.Attributes.Append(_xAuditPackageExecutionModeAttribute)
        taskElement.Attributes.Append(_xAuditPackageRunAsMasterAttribute)
        taskElement.Attributes.Append(_xAuditParentPackageExecutionIdVariableNameAttribute)
        taskElement.Attributes.Append(_xAuditThisPackageExecutionIdVariableNameAttribute)
        taskElement.Attributes.Append(_xAuditPackageExecutionStatusAttribute)
        taskElement.Attributes.Append(_xAuditPackageExecutionVariableNameAttribute)
        taskElement.Attributes.Append(_xAuditTableExecutionModeAttribute)
        taskElement.Attributes.Append(_xAuditedDatabaseConnectionNameAttribute)
        taskElement.Attributes.Append(_xAuditedDatabaseConnectionGUIDAttribute)
        taskElement.Attributes.Append(_xAuditTableExecutionIdVariableNameAttribute)
        taskElement.Attributes.Append(_xAuditTableSchemaNameAttribute)
        taskElement.Attributes.Append(_xAuditTableNameAttribute)
        taskElement.Attributes.Append(_xAuditTableStartRowCountActionAttribute)
        taskElement.Attributes.Append(_xAuditTableStartRowCountVariableNameAttribute)
        taskElement.Attributes.Append(_xAuditTableStartRowCountQueryAttribute)
        taskElement.Attributes.Append(_xAuditTableUpdateRowCountVariableNameAttribute)
        taskElement.Attributes.Append(_xAuditTableInsertRowCountActionAttribute)
        taskElement.Attributes.Append(_xAuditTableInsertRowCountVariableNameAttribute)
        taskElement.Attributes.Append(_xAuditTableInsertRowCountQueryAttribute)
        taskElement.Attributes.Append(_xAuditTableDeleteRowCountVariableNameAttribute)
        taskElement.Attributes.Append(_xAuditTableErrorRowCountVariableNameAttribute)
        taskElement.Attributes.Append(_xAuditTableEndingRowCountActionAttribute)
        taskElement.Attributes.Append(_xAuditTableEndingRowCountVariableNameAttribute)
        taskElement.Attributes.Append(_xAuditTableEndingRowCountQueryAttribute)
        taskElement.Attributes.Append(_xAuditTableExecutionStatusAttribute)
        taskElement.Attributes.Append(_xAuditTableExecutionVariableNameAttribute)
        taskElement.Attributes.Append(_xUserSelectedTaskNameAttribute)

        doc.AppendChild(taskElement)
    End Sub

    ''' <summary>
    ''' Initializes the task from the data stored in the package's XmlDocument.
    ''' </summary>
    ''' <param name="node">The Task's XmlNode</param>
    ''' <param name="infoEvents">IDTSComponentEvents Interface</param>
    <System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")> _
    <System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters", MessageId:="System.Exception.#ctor(System.String)")> _
    Sub LoadFromXML(ByVal node As System.Xml.XmlElement, ByVal infoEvents As IDTSInfoEvents) Implements IDTSComponentPersist.LoadFromXML
        If node Is Nothing Then
            Throw New ArgumentNullException("node")
        End If

        ' This might occur if the task's XML has been modified outside of the Business Intelligence
        ' Or SQL Server Workbenches.
        If node.Name <> "NCL.SSIS.ControlFlow.Audit" Then
            Throw New Exception("Unexpected task element when loading task.")
        Else
            Try
                _oAuditConfig.AuditDatabaseConnectionName = node.Attributes.GetNamedItem("AuditDatabaseConnectionName").Value
                _oAuditConfig.AuditDatabaseConnectionGUID = node.Attributes.GetNamedItem("AuditDatabaseConnectionGUID").Value
                _oAuditConfig.AuditPackageExecutionMode = CType(node.Attributes.GetNamedItem("AuditPackageExecutionMode").Value, AuditExecutionMode)
                _oAuditConfig.AuditPackageRunAsMaster = CType(node.Attributes.GetNamedItem("AuditPackageRunAsMaster").Value, AuditRunAsMaster)
                _oAuditConfig.AuditParentPackageExecutionIdVariableName = node.Attributes.GetNamedItem("AuditParentPackageExecutionIdVariableName").Value
                _oAuditConfig.AuditThisPackageExecutionIdVariableName = node.Attributes.GetNamedItem("AuditThisPackageExecutionIdVariableName").Value
                _oAuditConfig.AuditPackageExecutionStatus = CType(node.Attributes.GetNamedItem("AuditPackageExecutionStatus").Value, AuditExecutionStatus)
                _oAuditConfig.AuditPackageExecutionVariableName = node.Attributes.GetNamedItem("AuditPackageExecutionVariableName").Value
                _oAuditConfig.AuditTableExecutionMode = CType(node.Attributes.GetNamedItem("AuditTableExecutionMode").Value, AuditExecutionMode)
                _oAuditConfig.AuditedDatabaseConnectionName = node.Attributes.GetNamedItem("AuditedDatabaseConnectionName").Value
                _oAuditConfig.AuditedDatabaseConnectionGUID = node.Attributes.GetNamedItem("AuditedDatabaseConnectionGUID").Value
                _oAuditConfig.AuditTableExecutionIdVariableName = node.Attributes.GetNamedItem("AuditTableExecutionIdVariableName").Value
                _oAuditConfig.AuditTableSchemaName = node.Attributes.GetNamedItem("AuditTableSchemaName").Value
                _oAuditConfig.AuditTableName = node.Attributes.GetNamedItem("AuditTableName").Value
                _oAuditConfig.AuditTableStartRowCountAction = CType(node.Attributes.GetNamedItem("AuditTableStartRowCountAction").Value, AuditTableAction)
                _oAuditConfig.AuditTableStartRowCountVariableName = node.Attributes.GetNamedItem("AuditTableStartRowCountVariableName").Value
                _oAuditConfig.AuditTableStartRowCountQuery = node.Attributes.GetNamedItem("AuditTableStartRowCountQuery").Value
                _oAuditConfig.AuditTableUpdateRowCountVariableName = node.Attributes.GetNamedItem("AuditTableUpdateRowCountVariableName").Value
                _oAuditConfig.AuditTableInsertRowCountAction = CType(node.Attributes.GetNamedItem("AuditTableInsertRowCountAction").Value, AuditTableAction)
                _oAuditConfig.AuditTableInsertRowCountVariableName = node.Attributes.GetNamedItem("AuditTableInsertRowCountVariableName").Value
                _oAuditConfig.AuditTableInsertRowCountQuery = node.Attributes.GetNamedItem("AuditTableInsertRowCountQuery").Value
                _oAuditConfig.AuditTableDeleteRowCountVariableName = node.Attributes.GetNamedItem("AuditTableDeleteRowCountVariableName").Value
                _oAuditConfig.AuditTableErrorRowCountVariableName = node.Attributes.GetNamedItem("AuditTableErrorRowCountVariableName").Value
                _oAuditConfig.AuditTableEndingRowCountAction = CType(node.Attributes.GetNamedItem("AuditTableEndingRowCountAction").Value, AuditTableAction)
                _oAuditConfig.AuditTableEndingRowCountVariableName = node.Attributes.GetNamedItem("AuditTableEndingRowCountVariableName").Value
                _oAuditConfig.AuditTableEndingRowCountQuery = node.Attributes.GetNamedItem("AuditTableEndingRowCountQuery").Value
                _oAuditConfig.AuditTableExecutionStatus = CType(node.Attributes.GetNamedItem("AuditTableExecutionStatus").Value, AuditExecutionStatus)
                _oAuditConfig.AuditTableExecutionVariableName = node.Attributes.GetNamedItem("AuditTableExecutionVariableName").Value
                _oAuditConfig.UserSelectedTaskName = node.Attributes.GetNamedItem("UserSelectedTaskName").Value
            Catch
                Throw
            End Try
        End If
    End Sub
#End Region

#Region "IDTSBreakpointSite Members"
    Sub AcceptBreakpointManager(ByVal breakpointManager As BreakpointManager) Implements IDTSBreakpointSite.AcceptBreakpointManager
        If breakpointManager Is Nothing Then
            Throw New ArgumentNullException("breakpointManager")
        End If

        Me.bpm = breakpointManager
        Me.bpm.CreateBreakpointTarget(1, "Break when the container receives the OnBeforePackageAuditStartParent event.")
        Me.bpm.CreateBreakpointTarget(2, "Break when the container receives the OnAfterPackageAuditStartParent event.")
        Me.bpm.CreateBreakpointTarget(3, "Break when the container receives the OnAfterPackageAuditStartEnd event.")
        Me.bpm.CreateBreakpointTarget(4, "Break when the container receives the OnBeforePackageAuditStart event.")
        Me.bpm.CreateBreakpointTarget(5, "Break when the container receives the OnAfterPackageAuditStart event.")
        Me.bpm.CreateBreakpointTarget(6, "Break when the container receives the OnAfterPackageAuditEnd event.")
        Me.bpm.CreateBreakpointTarget(7, "Break when the container receives the OnBeforeTableAuditStart event.")
        Me.bpm.CreateBreakpointTarget(8, "Break when the container receives the OnAfterTableAuditStart event.")
        Me.bpm.CreateBreakpointTarget(9, "Break when the container receives the OnAfterTableAuditEnd event.")
    End Sub

    Property DebugMode() As Boolean Implements IDTSBreakpointSite.DebugMode
        Get
            Return Me.debugModeValue <> 0
        End Get
        Set(ByVal value As Boolean)
            'Interlocked.Exchange((Me.debugModeValue), IIf(value, 1, 0)) 'TODO: For performance reasons this should be changed to nested IF statements
            If value = True Then
                Interlocked.Exchange(Me.debugModeValue, 1)
            End If

            If value = False Then
                Interlocked.Exchange(Me.debugModeValue, 0)
            End If
        End Set
    End Property
#End Region

#Region "IDTSSuspend Members"
    Property SuspendRequired() As Boolean Implements IDTSSuspend.SuspendRequired
        Get
            Return Me.suspendRequiredValue <> 0
        End Get
        Set(ByVal value As Boolean)
            ' This lock is also taken by Suspend().  Since it is possible for the package to be
            ' suspended and resumed in quick succession, this property put might happen before
            ' the actual Suspend() call.  Without the lock, the Suspend() might reset the canExecute
            ' event after we set it to abort the suspension.
            SyncLock Me
                'Interlocked.Exchange((Me.suspendRequiredValue), IIf(value, 1, 0)) 'TODO: For performance reasons this should be changed to nested IF statements
                If value = True Then
                    Interlocked.Exchange(Me.suspendRequiredValue, 1)
                End If

                If value = False Then
                    Interlocked.Exchange(Me.suspendRequiredValue, 0)
                End If

                If Not value Then
                    ChangeEvent(canExecute, True)
                End If
            End SyncLock
        End Set
    End Property

    Sub ResumeExecution() Implements IDTSSuspend.ResumeExecution
        ChangeEvent(canExecute, True)
    End Sub

    Sub SuspendExecution() Implements IDTSSuspend.SuspendExecution
        ' This lock is also taken by the set SuspendRequired method.  It prevents this
        ' call from override an aborted suspension.  See comments in set SuspendRequired.
        SyncLock Me
            ' If a suspend is required, do it.
            If Me.suspendRequiredValue <> 0 Then
                ChangeEvent(canExecute, False)
            End If
        End SyncLock

        ' We can't return from Suspend until the task is "suspended".  This can happen
        ' one of two way: the suspended event occurs, indicating that the execute thread
        ' has suspended or the canExecute flag is set, indicating that a suspend is no
        ' longer required.
        Dim suspendOperationComplete As WaitHandle() = {suspended, canExecute}
        WaitHandle.WaitAny(suspendOperationComplete)
    End Sub
#End Region

#Region "Breakpoint Helper Functions"
    Private Sub CheckAndSuspend()
        ' Loop until we can execute.  The loop is required rather than a simple if
        ' because there is a time between the return from WaitOne and the reset that we
        ' might receive another Suspend call.  Suspend() will see that we are suspended
        ' and return.  So we need to rewait.
        While Not canExecute.WaitOne(0, False)
            ChangeEvent(suspended, True)
            canExecute.WaitOne()
            ChangeEvent(suspended, False)
        End While
    End Sub

    Private Sub CheckAndFireBreakpoint(ByVal events As IDTSComponentEvents, ByVal breakpointID As Integer)
        ' If the breakpoint is enabled, fire it.
        If Me.debugModeValue <> 0 AndAlso Me.bpm.IsBreakpointTargetEnabled(breakpointID) Then
            ' Enter a suspend mode before firing the breakpoint.  Firing the breakpoint
            ' will cause the runtime to call Suspend on this task.  Since we are blocked
            ' on the breakpoint, we are suspended, so indicate that.
            ChangeEvent(suspended, True)
            events.FireBreakpointHit(Me.bpm.GetBreakpointTarget(breakpointID))
            ChangeEvent(suspended, False)
        End If

        ' Check for a suspension for two reasons: 1. If we are at a point where we could
        ' fire a breakpoint, we are at a valid suspend point.  Even if we didn't hit a
        ' breakpoint, the runtime may have called suspend, so check for it.  2. Between
        ' the return from OnBreakpointHit and the reset of the event, it is possible to have
        ' received a suspend call that we returned from because we were suspended.  We need
        ' to be sure it is ok to continue executing now.
        CheckAndSuspend()
    End Sub

    <System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")> _
    <System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters", MessageId:="System.Exception.#ctor(System.String)")> _
    <System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")> _
    Shared Sub ChangeEvent(ByVal e As ManualResetEvent, ByVal shouldSet As Boolean)
        If e Is Nothing Then
            Throw New ArgumentNullException("e")
        End If

        Dim succeeded As Boolean

        If shouldSet Then
            succeeded = e.Set()
        Else
            succeeded = e.Reset()
        End If

        If Not succeeded Then
            Throw New Exception("Synchronization object failed.")
        End If
    End Sub
#End Region
End Class
